﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Resources;
using System.Globalization;
using System.Reflection;
using EnvDTE;
using SPVisualDev.VSAddin.Dialogs;
using SPVisualDev.Services;
using SPVisualDev.VSAddin.Dialogs.PropertySheets;
//using Microsoft.SharePoint;

namespace SPVisualDev.VSAddin.Dialogs
{
    public partial class DialogFeatureEditor : Form
    {
        private SPVisualDev.VSAddin.Connect m_addin_instance;
        private FeatureManager m_feature_manager;
        private SpecialProject m_special_project;
        private Dictionary<Guid, string> m_features_in_project = new Dictionary<Guid, string>();

        private string m_default_code_folder_init_value;
        private string m_default_code_namesapce_init_value;

        private ProjectItem m_feature_folder;
        private PropSheetFeatureInfo m_main_info;
        private string m_resource_editor_last_used_file;
        
        private string FeatureID
        {
            get { return txtFeatureID.Text; }
            set { txtFeatureID.Text = value; }
        }

        internal SpecialProject Project
        {
            get { return m_special_project; }
        }

        internal string DefaultCodeFolder
        {
            get { return txtDefaultCodeFolder.Text; }
        }

        internal string DefaultCodeNamespace
        {
            get { return txtDefaultCodeNamespace.Text; }
        }

        internal FeatureManager FeatureManager
        {
            get { return m_feature_manager; }
        }

        internal string DefaultResourceFile
        {
            get
            {
                if (txtPageGeneral_DefaultResourceFile.Text == "<Feature folder>\\Resources")
                    return Common.C_LOCAL_RESOURCE_IDENTIFIER;
                else
                    return txtPageGeneral_DefaultResourceFile.Text;
            }
            set
            {
                if (string.Compare(value, Common.C_LOCAL_RESOURCE_IDENTIFIER, true) == 0)
                {
                    txtPageGeneral_DefaultResourceFile.Text = "<Feature folder>\\Resources";
                }
                else
                {
                    txtPageGeneral_DefaultResourceFile.Text = value;
                }
            }
        }

        public DialogFeatureEditor(ProjectItem FeatureFolder, SPVisualDev.VSAddin.Connect AddinInstance)
        {
            InitializeComponent();

            m_addin_instance = AddinInstance;
            m_special_project = m_addin_instance.SpecialSolution.GetSpecialProject(FeatureFolder.ContainingProject);

            this.FormClosing += new FormClosingEventHandler(Dialog_FormClosing);
            this.Load += new EventHandler(Dialog_Load);

            this.lstPageElements_ContainingElements.SelectedIndexChanged += new EventHandler(lstPageElements_ContainingElements_SelectedIndexChanged);

            this.grdPageElements_Properties.PropertyValueChanged += new PropertyValueChangedEventHandler(PropertyGrid_PropertyValueChanged);
            this.grdPageElements_Properties.SelectedGridItemChanged += new SelectedGridItemChangedEventHandler(PropertyGrid_SelectedGridItemChanged);
            this.grdPageElements_Properties.SelectedObjectsChanged += new EventHandler(grdPageElements_Properties_SelectedObjectsChanged);

            this.grdPageGeneral_MainInfo.PropertyValueChanged += new PropertyValueChangedEventHandler(PropertyGrid_PropertyValueChanged);
            this.grdPageGeneral_MainInfo.SelectedGridItemChanged += new SelectedGridItemChangedEventHandler(PropertyGrid_SelectedGridItemChanged);

            this.txtDefaultCodeFolder.TextChanged += new EventHandler(txtDefaultCodeFolder_TextChanged);
            this.chkDefaultCodeNamespaceAuto.CheckedChanged += new EventHandler(chkDefaultCodeNamespaceAuto_CheckedChanged);

            m_feature_folder = FeatureFolder;

            InitializeForm();

        }

        void chkDefaultCodeNamespaceAuto_CheckedChanged(object sender, EventArgs e)
        {
            if (this.chkDefaultCodeNamespaceAuto.Checked)
            {
                this.txtDefaultCodeNamespace.Text = GetDefaultCodeNamespace();
            }

            this.txtDefaultCodeNamespace.Enabled = !this.chkDefaultCodeNamespaceAuto.Checked;
        }

        void txtDefaultCodeFolder_TextChanged(object sender, EventArgs e)
        {
            if (this.chkDefaultCodeNamespaceAuto.Checked)
            {
                this.txtDefaultCodeNamespace.Text = GetDefaultCodeNamespace();
            }
        }

        private void InitializeForm()
        {
            this.Text = m_feature_folder.Name;

            m_feature_manager = new FeatureManager(m_special_project, m_feature_folder);
            m_feature_manager.ReadContent();


            lstPageElements_ContainingElements.Sorted = true;
            btnPageElements_ImportContentType.Visible = false;

            string xmldoc_feature_file_path = Common.GetProjectItemPath(m_feature_folder.ProjectItems.Item("Feature.xml"));

            txtFeatureID.Text = m_feature_manager.FeatureID;
            this.DefaultResourceFile = m_feature_manager.FeatureDefaultResourceFile;


            m_main_info = new PropSheetFeatureInfo(this.DefaultResourceFile, m_feature_folder, null);
            m_main_info.Title.RawString = m_feature_manager.FeatureTitle;
            m_main_info.Description.RawString = m_feature_manager.FeatureDescription;

            grdPageGeneral_MainInfo.PropertySort = PropertySort.NoSort;
            grdPageGeneral_MainInfo.SelectedObject = m_main_info;

            grdPageElements_Properties.PropertySort = PropertySort.NoSort;

            string feature_scope = m_feature_manager.FeatureScope;
            m_main_info.Scope = FeatureScopeEnum.ScopeInvalid;
            if (!string.IsNullOrEmpty(feature_scope))
            {
                FeatureScopeEnum scope = FeatureScopeEnum.ScopeInvalid;
                try
                {
                    scope = (FeatureScopeEnum)Enum.Parse(typeof(FeatureScopeEnum), feature_scope, true);
                }
                catch { }

                if (scope != FeatureScopeEnum.ScopeInvalid)
                {
                    m_main_info.Scope = scope;
                }
            }

            m_main_info.Version = m_feature_manager.FeatureVersion;
            m_main_info.Hidden = m_feature_manager.FeatureHidden;
            m_main_info.ReceiverAssembly = m_feature_manager.FeatureEventReceiverAssembly;
            m_main_info.ReceiverClass = m_feature_manager.FeatureEventReceiverClass;

            if (this.FeatureID == string.Empty)
            {
                this.FeatureID = Guid.NewGuid().ToString("D").ToUpper();
            }

            if (string.IsNullOrEmpty(m_feature_manager.FeatureDefaultCodeFolder))
            {
                //For compatibility reasons, versions < 2.0
                string s = Common.GetProjectGlobalConfigKey(m_special_project.Project, "EventRecCodeInFeatureFolder");
                if (string.IsNullOrEmpty(s))
                {
                    this.txtDefaultCodeFolder.Text = "<Feature folder>\\CodeFiles";
                }
                else
                {
                    if (bool.Parse(s))
                    {
                        this.txtDefaultCodeFolder.Text = "<Feature folder>\\CodeFiles";
                    }
                    else
                    {
                        this.txtDefaultCodeFolder.Text = Common.GetProjectGlobalConfigKey(m_special_project.Project, "EventRecNSsuffix");
                        if (this.txtDefaultCodeFolder.Text == "")
                            this.txtDefaultCodeFolder.Text = "<Project root>\\CodeFiles";
                    }
                }
            }
            else
            {
                this.txtDefaultCodeFolder.Text = m_feature_manager.FeatureDefaultCodeFolder;
            }
            m_default_code_folder_init_value = this.txtDefaultCodeFolder.Text;


            if (string.IsNullOrEmpty(m_feature_manager.FeatureDefaultCodeNamespace))
            {
                this.txtDefaultCodeNamespace.Text = GetDefaultCodeNamespace();
                this.txtDefaultCodeNamespace.Enabled = false;
                this.chkDefaultCodeNamespaceAuto.Checked = true;
            }
            else
            {
                this.txtDefaultCodeNamespace.Text = m_feature_manager.FeatureDefaultCodeNamespace;
            }
            m_default_code_namesapce_init_value = this.txtDefaultCodeNamespace.Text;


            m_main_info.HasUnsavedResourceChanges = false;

            foreach (ElementInfo el_info in m_feature_manager.GetAllElements())
            {
                switch (el_info.ElementName)
                {
                    case "ListTemplate":
                        PropSheetListTemplate prop_sheet_LT = new PropSheetListTemplate(this.DefaultResourceFile, m_feature_folder, el_info);

                        prop_sheet_LT.SetNewSheetFlag(false);

                        AddElementToContainingList(prop_sheet_LT);
                        break;

                    case "ContentType":
                        PropSheetContentType prop_sheet_CT = new PropSheetContentType(this.DefaultResourceFile, m_feature_folder, el_info, m_special_project);

                        prop_sheet_CT.SetNewSheetFlag(false);

                        AddElementToContainingList(prop_sheet_CT);
                        break;

                    case "Module":
                        PropSheetModule prop_sheet_module = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info);
                        AddElementToContainingList(prop_sheet_module);
                        break;

                    case "ListInstance":
                        PropSheetListInstance prop_sheet_list_instance = new PropSheetListInstance(this.DefaultResourceFile, m_feature_folder, el_info);
                        AddElementToContainingList(prop_sheet_list_instance);
                        break;

                    case "CustomAction":
                        PropSheetCustomAction prop_sheet_ca = new PropSheetCustomAction(this.DefaultResourceFile, m_feature_folder, el_info);
                        AddElementToContainingList(prop_sheet_ca);
                        break;

                    case "Field":
                        PropSheetField prop_sheet_field = new PropSheetField(this.DefaultResourceFile, m_feature_folder, el_info);
                        AddElementToContainingList(prop_sheet_field);
                        break;
                }
            }


            EnumAllFeaturesInProject();
            foreach (KeyValuePair<Guid, string> kvp in m_features_in_project)
            {
                cboPageActivationDep_FeatureToAdd.Items.Add(kvp.Value + ":" + kvp.Key.ToString().ToUpper());
            }

            foreach (Guid gid in m_feature_manager.ActivationDependencies)
            {
                if (m_features_in_project.ContainsKey(gid))
                {
                    lstPageActivationDep_List.Items.Add(m_features_in_project[gid] + ":" + gid.ToString("D").ToUpper());
                }
                else
                {
                    lstPageActivationDep_List.Items.Add("(feature not in project):" + gid.ToString("D").ToUpper());
                }
            }


            txtPageGeneral_DefaultResourceFile.Leave += new EventHandler(txtPageGeneral_DefaultResourceFile_Leave);
            txtPageGeneral_DefaultResourceFile.KeyDown += new KeyEventHandler(txtPageGeneral_DefaultResourceFile_KeyDown);


            btnPageElements_PickResource.Enabled = false;

            if (this.lstPageElements_ContainingElements.Items.Count > 0)
            {
                this.lstPageElements_ContainingElements.SelectedIndex = 0;
            }

        }

        private void Dialog_Load(object sender, EventArgs e)
        {
            MoveSplitter(grdPageGeneral_MainInfo, 150);
        }

        private void EnumAllFeaturesInProject()
        {
            m_features_in_project = new Dictionary<Guid, string>();
            ProjectItem features_root = m_feature_folder.Collection.Parent as ProjectItem;
            foreach (ProjectItem item in features_root.ProjectItems)
            {
                if (item.Kind != Constants.vsProjectItemKindPhysicalFolder)
                    continue;

                string path = Common.GetProjectItemPath(item);
                if (!File.Exists(path + "\\Feature.xml"))
                    continue;

                try
                {
                    XmlDocument xmldoc = new XmlDocument();
                    xmldoc.Load(path + "\\Feature.xml");
                    string id = Common.GetXmlAttribute(xmldoc.DocumentElement, "ID");
                    m_features_in_project.Add(new Guid(id.Trim().ToUpper()), item.Name);
                }
                catch { }
            }
        }

        private void txtPageGeneral_DefaultResourceFile_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyCode == Keys.Enter)
                {
                    this.tabPageGeneral.Select();
                }
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void txtPageGeneral_DefaultResourceFile_Leave(object sender, EventArgs e)
        {
            try
            {
                if (HasPendingResourceChanges())
                {
                    string msg = "All unsaved resource changes will be discarded if changing the default resource file. Do you want to save them?";

                    DialogResult result = MessageBox.Show(msg, "Prompt", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);

                    if (result == DialogResult.None || result == DialogResult.Cancel)
                    {
                        return;
                    }
                    else if (result == DialogResult.Yes)
                    {
                        SaveAllPendingResourceChanges();
                    }
                }

                this.DefaultResourceFile = txtPageGeneral_DefaultResourceFile.Text;

                InvalidateResourceCache();

                grdPageElements_Properties.Refresh();
                grdPageGeneral_MainInfo.Refresh();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void Dialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                if (this.DialogResult != DialogResult.OK)
                {
                    if (MessageBox.Show("Discard changes?", "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.OK)
                    {
                        e.Cancel = true;
                        return;
                    }
                }

                if (this.DialogResult != DialogResult.OK)
                    return;

                bool isValid = ValidateForm(false);
                if (!isValid)
                {
                    e.Cancel = true;
                    return;
                }

                SaveFeatureChanges();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void PropertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
        {
            try
            {
                RefreshPickResourceButtonStatus(sender as PropertyGrid);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void RefreshPickResourceButtonStatus(PropertyGrid grid)
        {
            if (grid.SelectedGridItem == null)
            {
                btnPageElements_PickResource.Enabled = false;
                btnPageGeneral_PickResource.Enabled = false;

                return;
            }

            if (grid.SelectedGridItem.Value is ResourceStringContainer)
            {
                btnPageElements_PickResource.Enabled = true;
                btnPageGeneral_PickResource.Enabled = true;
            }
            else
            {
                btnPageElements_PickResource.Enabled = false;
                btnPageGeneral_PickResource.Enabled = false;
            }
        }

        private void MoveSplitter(PropertyGrid propertyGrid, int x)
        {
            object propertyGridView = typeof(PropertyGrid).InvokeMember("gridView", BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null, propertyGrid, null);
            propertyGridView.GetType().InvokeMember("MoveSplitterTo", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, propertyGridView, new object[] { x });

            propertyGrid.Focus();
        }

        private void grdPageElements_Properties_SelectedObjectsChanged(object sender, EventArgs e)
        {
            try
            {
                btnPageElements_ImportContentType.Visible = false;

                lstPageElements_ContainingElements.Refresh();

                if (grdPageElements_Properties.SelectedObject == null)
                    return;

                if (grdPageElements_Properties.SelectedObject.GetType() == typeof(PropSheetContentType))
                {
                    btnPageElements_ImportContentType.Visible = true;
                }
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void PropertyGrid_PropertyValueChanged(object sender, PropertyValueChangedEventArgs e)
        {
            try
            {
                PropertyGrid grid = sender as PropertyGrid;

                if (e.ChangedItem.PropertyDescriptor.PropertyType == typeof(ResourceStringContainer))
                {
                    ResourceStringContainer old_value = e.OldValue as ResourceStringContainer;
                    ResourceStringContainer new_value = e.ChangedItem.Value as ResourceStringContainer;

                    if (ResourceHelper.IsResourceString(old_value.RawString))
                    {
                        string msg = "Changing the resource key will discard all changes made since last save for this resource key. Do you want to change it?";
                        if (MessageBox.Show(msg, "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.OK)
                        {
                            ResourceStringContainer res_container = new ResourceStringContainer(new_value.RawString, this.DefaultResourceFile, m_feature_folder);
                            e.ChangedItem.PropertyDescriptor.SetValue(grid.SelectedObject, res_container);
                        }
                        else
                        {
                            e.ChangedItem.PropertyDescriptor.SetValue(grid.SelectedObject, old_value);
                        }

                        grid.Refresh();

                    }
                }

                if (e.ChangedItem.PropertyDescriptor.Name == "ReceiverClass")
                {
                    CodeClass cls = m_special_project.Project.CodeModel.CodeTypeFromFullName(e.ChangedItem.Value as string) as CodeClass;
                    if (cls != null)
                    {
                        if (!Common.HasBaseCodeClass(cls, "SPFeatureReceiver"))
                        {
                            MessageBox.Show("Selected class must inherit from SPFeatureEventReceiver.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

                            e.ChangedItem.PropertyDescriptor.SetValue(grid.SelectedObject, e.OldValue);
                            grid.Refresh();
                        }
                        else
                        {
                            if (cls.InfoLocation == vsCMInfoLocation.vsCMInfoLocationProject)
                            {
                                string assemblyName = Common.GetTargetBuildAssemblyName(m_feature_folder.ContainingProject, true);
                                if (string.IsNullOrEmpty(assemblyName))
                                {
                                    m_main_info.ReceiverAssembly = "(will be generated when the project is built next time and the feature is refreshed.)";
                                }
                                else
                                {
                                    m_main_info.ReceiverAssembly = assemblyName;
                                }
                            }
                            else
                            {
                                m_main_info.ReceiverAssembly = "";
                            }

                            m_feature_manager.GenerateEventReceivers();

                            grid.Refresh();
                        }
                    }
                }

                if (e.ChangedItem.PropertyDescriptor.Name == "EventReceiverClasses")
                {
                    m_feature_manager.GenerateEventReceivers();
                    grid.Refresh();
                }

                if (grid.Name == "grdPageElements_Properties")
                {
                    if (lstPageElements_ContainingElements.SelectedIndex != -1)
                        lstPageElements_ContainingElements.Items[lstPageElements_ContainingElements.SelectedIndex] = grid.SelectedObject;

                    lstPageElements_ContainingElements.Refresh();
                }


            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        public void AddElementToContainingList(object PropertySheet)
        {
            lstPageElements_ContainingElements.Items.Add(PropertySheet);
        }

        private void SaveFeatureChanges()
        {

            string skip_files = m_special_project.GetUserSettingsValue("SkipFilesPushDown");

            if (HasPendingResourceChanges())
                SaveAllPendingResourceChanges();

            foreach (object element in lstPageElements_ContainingElements.Items)
            {

                IPropertySheet sheet = element as IPropertySheet;

                if (sheet.ElementFileNameHasChanged)
                {
                    List<CodeClass> l1 = new List<CodeClass>(sheet.ElementInfo.AttachedEventReceiverClasses);
                    List<CodeClass> l2 = new List<CodeClass>(sheet.ElementInfo.AttachedEventReceiverClassesInit);
                    List<EventReceiverInfo> l3 = new List<EventReceiverInfo>(sheet.ElementInfo.EventReceivers);
                    List<EventReceiverInfo> l4 = new List<EventReceiverInfo>(sheet.ElementInfo.EventReceiversInit);

                    m_feature_manager.RemoveElement(sheet.ElementInfo.ID, false);
                    ElementInfo newElementInfo = m_feature_manager.AddElement(sheet.ElementFileName, sheet.PropXmlNode.OuterXml);

                    newElementInfo.AttachedEventReceiverClasses = l1;
                    newElementInfo.AttachedEventReceiverClassesInit = l2;
                    newElementInfo.EventReceivers = l3;
                    newElementInfo.EventReceiversInit = l4;

                    sheet.ElementInfo = newElementInfo;
                }

                XmlElement xel = sheet.PropXmlNode;

                string element_name = xel.LocalName;

                //New elements
                if (sheet.ElementInfo.New)
                {
                    if (element_name == "ListTemplate")
                    {
                        PropSheetListTemplate sheet2 = element as PropSheetListTemplate;
                        bool b = AddListTemplateFiles(sheet2, sheet2.OriginalType.ToString());
                        if (!b)
                            return;
                    }
                    else if (element_name == "ContentType")
                    {
                        //PropSheetContentType obj = elment as PropSheetContentType;
                        //AddContentTypeFiles(obj);
                    }
                    else if (element_name == "Module")
                    {
                        PropSheetModule prop_sheet_module = element as PropSheetModule;

                        ProjectItem module_folder = null;
                        string folder_name = Common.FilterIllegalCharsInFileName(GetElementFolderName(prop_sheet_module.Name));
                        try
                        {
                            module_folder = m_feature_folder.ProjectItems.AddFolder(folder_name, Constants.vsProjectItemKindPhysicalFolder);
                        }
                        catch
                        {
                            MessageBox.Show("Feature already contains an element folder named '" + folder_name + "'. Element files will be skipped.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        if (prop_sheet_module.SubType == "WebPart")
                            AddWebPartFiles(prop_sheet_module, module_folder);
                        else if (prop_sheet_module.SubType == "MasterPage")
                            AddMasterPage(prop_sheet_module, module_folder);
                    }
                }

            }


            m_feature_manager.FeatureTitle = m_main_info.Title.RawString;
            m_feature_manager.FeatureDescription = m_main_info.Description.RawString;
            m_feature_manager.FeatureID = this.FeatureID;
            m_feature_manager.FeatureScope = m_main_info.Scope.ToString();
            m_feature_manager.FeatureDefaultResourceFile = this.DefaultResourceFile;
            m_feature_manager.FeatureHidden = m_main_info.Hidden;
            m_feature_manager.FeatureVersion = m_main_info.Version;

            string s;
            if (this.txtDefaultCodeFolder.Text.StartsWith("<Project root>\\", StringComparison.OrdinalIgnoreCase) ||
                this.txtDefaultCodeFolder.Text.StartsWith("<Feature folder>\\", StringComparison.OrdinalIgnoreCase))
            {
                s = this.txtDefaultCodeFolder.Text;
            }
            else
            {
                if (this.txtDefaultCodeFolder.Text.StartsWith("\\"))
                {
                    s = "<Project root>" + this.txtDefaultCodeFolder.Text;
                }
                else
                {
                    s = "<Project root>\\" + this.txtDefaultCodeFolder.Text;
                }
            }
            if (m_default_code_folder_init_value != this.txtDefaultCodeFolder.Text)
            {
                m_feature_manager.FeatureDefaultCodeFolder = s;
            }

            if (this.chkDefaultCodeNamespaceAuto.Checked)
                this.txtDefaultCodeNamespace.Text = string.Empty;

            if (m_default_code_namesapce_init_value != this.txtDefaultCodeNamespace.Text)
            {
                m_feature_manager.FeatureDefaultCodeNamespace = this.txtDefaultCodeNamespace.Text;
            }

            m_feature_manager.FeatureEventReceiverAssembly = m_main_info.ReceiverAssembly;
            m_feature_manager.FeatureEventReceiverClass = m_main_info.ReceiverClass;

            m_feature_manager.WriteContent(false);

            return;
        }

        private string GetDefaultCodeNamespace()
        {
            string s = this.txtDefaultCodeFolder.Text;
            if (this.txtDefaultCodeFolder.Text.StartsWith("<Project root>\\", StringComparison.OrdinalIgnoreCase))
            {
                s = Common.FilterIllegalCharsInFileName(m_special_project.Project.Name) + "." + this.txtDefaultCodeFolder.Text.Replace("<Project root>\\", "").Replace("\\", ".");
            }
            else if (this.txtDefaultCodeFolder.Text.StartsWith("<Feature folder>\\", StringComparison.OrdinalIgnoreCase))
            {
                s = Common.FilterIllegalCharsInFileName(m_special_project.Project.Name) + ".Features." + Common.FilterIllegalCharsInFileName(m_feature_folder.Name);
            }
            else
            {
                s = Common.FilterIllegalCharsInFileName(m_special_project.Project.Name) + "." + this.txtDefaultCodeFolder.Text.Replace("\\", ".");
            }

            s = s.Replace(".12", "");

            return s;
        }

        private void lstPageElements_ContainingElements_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (lstPageElements_ContainingElements.SelectedItem == null)
                {
                    grdPageElements_Properties.SelectedObject = null;
                    grdPageElements_Properties.Refresh();
                    return;
                }

                if (lstPageElements_ContainingElements.SelectedItem is PropSheetContentType)
                {
                    bool b = (lstPageElements_ContainingElements.SelectedItem as PropSheetContentType).ElementInfo.New;
                    (lstPageElements_ContainingElements.SelectedItem as PropSheetContentType).SetNewSheetFlag(b);
                }
                else if (lstPageElements_ContainingElements.SelectedItem is PropSheetListTemplate)
                {
                    bool b = (lstPageElements_ContainingElements.SelectedItem as PropSheetListTemplate).ElementInfo.New;
                    (lstPageElements_ContainingElements.SelectedItem as PropSheetListTemplate).SetNewSheetFlag(b);
                }

                grdPageElements_Properties.SelectedObject = lstPageElements_ContainingElements.SelectedItem;
                grdPageElements_Properties.Refresh();

                grdPageElements_Properties.Focus();
            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageElements_AddFeatureElement_Click(object sender, EventArgs e)
        {
            try
            {

                string selected_element_info = null;

                using (DialogElementSelector dialog = new DialogElementSelector())
                {
                    DialogResult result = dialog.ShowDialog(this);
                    if (result != DialogResult.OK)
                        return;

                    if (string.IsNullOrEmpty(dialog.SelectedItem))
                        return;

                    selected_element_info = dialog.SelectedItem;
                }


                ElementInfo el_info;
                
                switch (selected_element_info)
                {
                    case "ListTemplate":

                        el_info = m_feature_manager.AddElement(null, "<ListTemplate/>");

                        PropSheetListTemplate prop_sheet_lt = new PropSheetListTemplate(this.DefaultResourceFile, m_feature_folder, el_info);

                        prop_sheet_lt.Type = int.Parse(FindNextUniqeListDefinitionId(10001).ToString());
                        prop_sheet_lt.SecurityBits = 11;
                        prop_sheet_lt.Name = "";
                        //prop_sheet_lt.OriginalType = prop_sheet_lt.FindOriginalTypeByTypeName(selected_element_info[1]); 
                        prop_sheet_lt.SetNewSheetFlag(true);

                        grdPageElements_Properties.SelectedObject = prop_sheet_lt;
                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_lt);

                        break;

                    case "ContentType":

                        el_info = m_feature_manager.AddElement(null, "<ContentType><FieldRefs xmlns=\"" + Common.C_MS_SHAREPOINT_XMLNS + "\"/></ContentType>");

                        PropSheetContentType prop_sheet_ct = new PropSheetContentType(this.DefaultResourceFile, m_feature_folder, el_info, m_special_project);

                        /*
                        string type = selected_element_info[1];
                        if (type == "Inherit from built-in types")
                        {
                            prop_sheet_ct.InvokeIDSelector(1);
                        }
                        if (type == "Inherit from site content types")
                        {
                            prop_sheet_ct.InvokeIDSelector(2);
                        }
                        if (type == "Custom")
                        {
                            prop_sheet_ct.InvokeIDSelector(3);
                        }
                        */

                        prop_sheet_ct.SetNewSheetFlag(true);

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_ct);

                        /*
                        if (type == "Import a content type")
                        {
                            ImportContentType(prop_sheet_ct);
                        }
                        */

                        break;

                    case "Module":
                        
                        el_info = m_feature_manager.AddElement(null, "<Module/>");

                        PropSheetModule prop_sheet_module = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info);

                        prop_sheet_module.Name = Common.GetSafeName(Common.GetProjectItemPath(m_feature_folder), "Module");
                        prop_sheet_module.Path = prop_sheet_module.Name;

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_module);
                        break;

                    case "ListInstance":
                        
                        el_info = m_feature_manager.AddElement(null, "<ListInstance/>");

                        PropSheetListInstance prop_sheet_list_instance = new PropSheetListInstance(this.DefaultResourceFile, m_feature_folder, el_info);
                        prop_sheet_list_instance.FeatureId = m_feature_manager.FeatureID;

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_list_instance);
                        break;

                    case "CustomAction":
                        
                        el_info = m_feature_manager.AddElement(null, "<CustomAction/>");

                        PropSheetCustomAction prop_sheet_ca = new PropSheetCustomAction(this.DefaultResourceFile, m_feature_folder, el_info);
                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_ca);
                        break;

                    case "WebPart":
                        
                        el_info = m_feature_manager.AddElement(null, "<Module/>");

                        PropSheetModule prop_sheet_webpart = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info);
                        prop_sheet_webpart.Name = Common.GetSafeName(Common.GetProjectItemPath(m_feature_folder), "WebPart");
                        prop_sheet_webpart.Path = prop_sheet_webpart.Name;
                        prop_sheet_webpart.Url.RawString = "_catalogs/wp";
                        prop_sheet_webpart.SubType = "WebPart";

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_webpart);
                        break;

                    case "MasterPage":
                        
                        el_info = m_feature_manager.AddElement(null, "<Module/>");

                        PropSheetModule prop_sheet_master_page = new PropSheetModule(this.DefaultResourceFile, m_feature_folder, el_info);
                        prop_sheet_master_page.Name = Common.GetSafeName(Common.GetProjectItemPath(m_feature_folder), "MasterPage");
                        prop_sheet_master_page.Path = prop_sheet_master_page.Name;
                        prop_sheet_master_page.Url.RawString = "_catalogs/masterpage";
                        prop_sheet_master_page.SubType = "MasterPage";

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_master_page);

                        break;

                    case "Field":
                        
                        el_info = m_feature_manager.AddElement(null, "<Field/>");

                        PropSheetField prop_sheet_field = new PropSheetField(this.DefaultResourceFile, m_feature_folder, el_info);

                        prop_sheet_field.ID = Guid.NewGuid().ToString("B");
                        prop_sheet_field.Type = "Text";

                        lstPageElements_ContainingElements.SelectedIndex = lstPageElements_ContainingElements.Items.Add(prop_sheet_field);
                        break;
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageElements_RemoveFeatureElement_Click(object sender, EventArgs e)
        {
            try
            {
                if (lstPageElements_ContainingElements.SelectedItems.Count == 0)
                    return;


                DialogResult res = MessageBox.Show(string.Format("Caution! Element '{0}' will immediately be deleted from this feature. Do you want to proceed?", lstPageElements_ContainingElements.SelectedItem.ToString()), "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
                if (res != DialogResult.Yes)
                    return;



                IPropertySheet selected_item = lstPageElements_ContainingElements.SelectedItem as IPropertySheet;

                if (selected_item.ElementInfo.ElementName == "Module" ||
                    selected_item.ElementInfo.ElementName == "ListTemplate")
                {
                    XmlElement el = selected_item.ElementInfo.XmlElementNode;

                    if (el.GetAttribute("Name") != "")
                    {
                        ProjectItem item = null;
                        try
                        {
                            item = m_feature_folder.ProjectItems.Item(el.GetAttribute("Name"));
                        }
                        catch { }

                        if (item != null)
                        {
                            if (item.Kind == Constants.vsProjectItemKindPhysicalFolder)
                            {
                                m_feature_manager.RemoveFeatureXMLElementFile(item.Name, true);
                                m_feature_manager.CommitChangesToFeatureXML();

                                item.Delete();

                            }
                        }
                    }
                }

                m_feature_manager.RemoveElement(selected_item.ElementInfo.ID, true);

                lstPageElements_ContainingElements.Items.RemoveAt(lstPageElements_ContainingElements.SelectedIndex);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private bool AddListTemplateFiles(PropSheetListTemplate element, string TemplateToUse)
        {
            string templates_path = element.OriginalType.TemplateFilesPath;
            if (string.IsNullOrEmpty(templates_path))
                throw new Exception("List templates path can not be empty.");

            templates_path = "\\TEMPLATE\\FEATURES" + templates_path;
            if (!Connect.S_Client_Install)
            {
                if (!Directory.Exists(SharePointLibrary.GetSharePointInstallPath() + templates_path))
                    throw new Exception("Can not find templates path '" + templates_path + "'");
            }
            
            if (string.IsNullOrEmpty(element.Name))
            {
                MessageBox.Show("List template type " + element.Type.ToString() + " name can not be null. Operation is canceled.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            string safe_element_name = Common.FilterIllegalCharsInFileName(GetElementFolderName(element.Name));
            if (CheckIfElementFolderExists(safe_element_name))
            {
                MessageBox.Show("An element folder with the name '" + safe_element_name + "' already exists in this feature or in the same path but excluded from the project. Operation is canceled.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }

            ProjectItem list_files_dir = null;
            if (!string.IsNullOrEmpty(templates_path))
            {
                list_files_dir = m_feature_folder.ProjectItems.AddFolder(safe_element_name, Constants.vsProjectItemKindPhysicalFolder);

                if (Connect.S_Client_Install)
                {
                    string[] files = m_special_project.ServiceProxy.EnumerateFilesIn12HiveDirectory(templates_path);
                    foreach (string file in files)
                    {
                        string tmp_path = Path.GetTempPath() + "\\" + file;
                        if (File.Exists(tmp_path))
                            File.Delete(tmp_path);

                        using (Stream stream = m_special_project.ServiceProxy.GetFileIn12Hive(templates_path + "\\" + file))
                        {
                            Common.WriteStreamToFile(stream, tmp_path);
                        }

                        
                        try
                        {
                            list_files_dir.ProjectItems.AddFromFileCopy(tmp_path);
                        }
                        finally
                        {
                            if (File.Exists(tmp_path))
                                File.Delete(tmp_path);
                        }
                    }
                }
                else
                {
                    string[] files = System.IO.Directory.GetFiles(SharePointLibrary.GetSharePointInstallPath() + templates_path);
                    foreach (string file in files)
                    {
                        list_files_dir.ProjectItems.AddFromFileCopy(file);
                    }
                }
            }
            else
            {
                list_files_dir = m_feature_folder.ProjectItems.AddFolder(safe_element_name, Constants.vsProjectItemKindPhysicalFolder);
            }

            return true;
        }

        private bool CheckIfElementFolderExists(string FolderName)
        {
            ProjectItem folder = null;
            try
            {
                folder = m_feature_folder.ProjectItems.Item(FolderName);
                return true;
            }
            catch
            {
            }

            if (System.IO.Directory.Exists(Common.GetProjectItemPath(m_feature_folder) + "\\" + FolderName))
                return true;

            return false;
        }

        private void AddWebPartFiles(PropSheetModule element, ProjectItem element_folder)
        {
            string code_ns = m_feature_folder.ContainingProject.Properties.Item("RootNamespace").Value.ToString();
            string feature_prefix = Common.FilterIllegalCharsInFileName(m_feature_folder.Name);
            if (string.IsNullOrEmpty(Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "WebPartsNSsuffix")))
                code_ns += ".UI.Webparts." + feature_prefix;
            else
                code_ns += "." + Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "WebPartsNSsuffix") + "." + feature_prefix;

            ProjectItem web_part_code_folder;
            if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "WPCodeInFeatureFolder") == "True")
                web_part_code_folder = element_folder;
            else
                web_part_code_folder = Common.CreateProjectItemPath(element_folder.ContainingProject,
                    Common.GetProjectGlobalConfigKey(element_folder.ContainingProject, "WebPartsNSsuffix").Replace(".", "\\") + "\\" + feature_prefix);

            try
            {
                string template_path;
                ProjectItem item;

                template_path = Common.GetItemTemplatePath(web_part_code_folder.ContainingProject, "SPVisualDev Web Part.zip", true);
                web_part_code_folder.ProjectItems.AddFromTemplate(template_path, GetElementFolderName(element.Name));

                item = web_part_code_folder.ProjectItems.Item(element.Name + ".cs");
                Common.SetNamespaceInCodeFile(ref item, code_ns);
                item.Document.Close(vsSaveChanges.vsSaveChangesYes);

                template_path = Common.GetItemTemplatePath(web_part_code_folder.ContainingProject, "SPVisualDev Web Part definition (webpart).zip", true);
                element_folder.ProjectItems.AddFromTemplate(template_path, GetElementFolderName(element.Name));

                item = element_folder.ProjectItems.Item(element.Name + ".webpart");
                item.Document.ReplaceText("$namespace$", code_ns, 0);

                string asm_name;
                if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "AssemblyBuildType") == "GAC")
                {
                    asm_name = Common.GetTargetBuildAssemblyName(m_feature_folder.ContainingProject, false);
                    if (asm_name.IndexOf("PublicKeyToke=null") != -1)
                        MessageBox.Show("The assembly is not signed with a public key token.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                }
                else
                {
                    asm_name = m_feature_folder.ContainingProject.Properties.Item("AssemblyName").Value.ToString();
                }

                item.Document.ReplaceText("$typename$", code_ns + "." + Common.FilterIllegalCharsInFileName(GetElementFolderName(element.Name)) + ", " + asm_name, 0);
                item.Document.ReplaceText("$assembly$", asm_name, 0);
                item.Name = element.Name + ".webpart";
                item.Document.Close(vsSaveChanges.vsSaveChangesYes);

            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to set web part files. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

        }

        private void AddMasterPage(PropSheetModule element, ProjectItem element_folder)
        {
            try
            {
                string template_path = Common.GetItemTemplatePath(element_folder.ContainingProject, "Master page (minimal no code behind).zip", true);
                element_folder.ProjectItems.AddFromTemplate(template_path, GetElementFolderName(element.Name));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to add master page. " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void btnPageGeneral_GenerateID_Click(object sender, EventArgs e)
        {
            try
            {
                if (MessageBox.Show("Do you want to generate a new feature ID?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    txtFeatureID.Text = Guid.NewGuid().ToString("D").ToUpper();
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        
        private void btnOK_Click(object sender, EventArgs e)
        {
            try
            {
                //if (m_main_info.EventReceiver)
                //{
                //    if (Common.GetProjectGlobalConfigKey(m_feature_folder.ContainingProject, "AssemblyBuildType") != "GAC")
                //        MessageBox.Show("Event receivers can not run if the project build type is not GAC. Please change it in artifact configuration menu for correct behavior.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                //}

                this.DialogResult = DialogResult.OK;
                this.Close();

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }
        

        private int FindNextUniqeListDefinitionId(int Start)
        {
            bool b = true;

            while (b)
            {
                bool found = false;
                foreach (IPropertySheet sheet in this.lstPageElements_ContainingElements.Items)
                {
                    if (sheet.ElementInfo.ElementName == "ListTemplate")
                    {
                        int type = (sheet as PropSheetListTemplate).Type;
                        if (type == Start)
                        {
                            found = true;
                            break;
                        }

                    }
                }

                if (!found)
                {
                    b = false;
                }
                else
                {
                    Start++;

                    if (Start > 65535)
                        return 65535;
                }
            }

            return Start;
        }

        private int CountListTemplatesOfType(int Type)
        {
            int count = 0;

            foreach (IPropertySheet sheet in this.lstPageElements_ContainingElements.Items)
            {
                if (sheet.ElementInfo.ElementName == "ListTemplate")
                {
                    int type = (sheet as PropSheetListTemplate).Type;
                    if (type == Type)
                    {
                        count++;
                    }
                }
            }

            return count;
        }

        private int CountContentTypesWithID(string ID)
        {
            int count = 0;

            foreach (IPropertySheet sheet in this.lstPageElements_ContainingElements.Items)
            {
                if (sheet.ElementInfo.ElementName == "ContentType")
                {
                    string id = (sheet as PropSheetContentType).ID;
                    if (id.Equals(ID, StringComparison.OrdinalIgnoreCase))
                    {
                        count++;
                    }
                }
            }

            return count;
        }

        private string GetElementFolderName(string RawString)
        {
            if (ResourceHelper.IsResourceString(RawString))
            {
                return ResourceHelper.ParseResourceKeyFromRawString(RawString);
            }
            else
            {
                return RawString;
            }
        }

        private void btnPageGeneral_DefaultResourceFilePick_Click(object sender, EventArgs e)
        {
            try
            {
                if (!CheckForPendingResourceChanges())
                    return;

                try
                {
                    using (DialogSelectResource dialog = new DialogSelectResource(m_feature_folder, false, this.DefaultResourceFile))
                    {
                        DialogResult res = dialog.ShowDialog(this);
                        if (res == DialogResult.OK && !string.IsNullOrEmpty(dialog.ResourceFileName))
                        {
                            this.DefaultResourceFile = dialog.ResourceFileName;
                        }
                    }
                }
                finally
                {
                    InvalidateResourceCache();

                    grdPageElements_Properties.Refresh();
                    grdPageGeneral_MainInfo.Refresh();
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageGeneral_DefaultResourceFileNew_Click(object sender, EventArgs e)
        {
            try
            {
                if (!CheckForPendingResourceChanges())
                    return;

                try
                {
                    using (DialogSelectResource dialog = new DialogSelectResource(m_feature_folder, true, this.DefaultResourceFile))
                    {
                        DialogResult res = dialog.ShowDialog(this);
                        if (res == DialogResult.OK && !string.IsNullOrEmpty(dialog.ResourceFileName))
                        {
                            this.DefaultResourceFile = dialog.ResourceFileName;
                        }
                    }
                }
                finally
                {
                    InvalidateResourceCache();

                    grdPageElements_Properties.Refresh();
                    grdPageGeneral_MainInfo.Refresh();
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void InvalidateResourceCache()
        {
            foreach (IPropertySheet sheet in lstPageElements_ContainingElements.Items)
            {
                sheet.InvalidateResourceChache();
                sheet.SetNewDefaultResourceFile(this.DefaultResourceFile);
            }

            m_main_info.InvalidateResourceChache();
            m_main_info.SetNewDefaultResourceFile(this.DefaultResourceFile);
        }

        private void ImportContentType(PropSheetContentType prop_sheet)
        {
            if (lstPageElements_ContainingElements.SelectedItem == null)
                return;

            
            bool useService = SPVisualDev.VSAddin.Connect.S_Client_Install;
            if (!useService)
            {
                useService = SharePointLibrary.CheckIf32bitOn64();
            }



            string element_file_name = prop_sheet.ElementFileName;
            int element_id = prop_sheet.ElementInfo.ID;

            using (DialogSharePointExplorer explorer = new DialogSharePointExplorer())
            {
                explorer.SPExplorer.ShowContentTypeGroups = true;
                explorer.SPExplorer.ShowContentTypes = true;
                explorer.SPExplorer.ShowFeatures = false;
                explorer.SPExplorer.ShowFields = false;
                explorer.SPExplorer.ShowSolutions = false;
                explorer.SPExplorer.ShowLists = false;

                explorer.Message = "Pick a content type to import.";
                explorer.CurrentProject = m_special_project;

                DialogResult res = explorer.ShowDialog(this);
                if (res != DialogResult.OK)
                    return;

                XmlElement root = explorer.SelectedContentType as XmlElement;
                if (root == null)
                {
                    string msg = "No content type selected.";
                    MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    return;
                }


                XmlElement el = root.FirstChild as XmlElement;
                m_feature_manager.RemoveElement(element_id, false);

                ElementInfo el_info = m_feature_manager.AddElement(element_file_name, el.OuterXml);
                prop_sheet = new PropSheetContentType(this.DefaultResourceFile, m_feature_folder, el_info, m_special_project);
 
                lstPageElements_ContainingElements.Items[lstPageElements_ContainingElements.SelectedIndex] = prop_sheet;
                grdPageElements_Properties.SelectedObject = prop_sheet;
                grdPageElements_Properties.Refresh();

                string msg2 = "Should all field definitions that belongs to this contentype be imported too?";
                DialogResult res2 = MessageBox.Show(msg2, "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (res2 == DialogResult.Yes)
                {
                    foreach (XmlNode node in root.GetElementsByTagName("Field"))
                    {
                        XmlElement el2 = node as XmlElement;
                        if (el2 == null)
                            continue;

                        List<XmlAttribute> list = new List<XmlAttribute>();
                        foreach (XmlAttribute attr in el2.Attributes)
                        {
                            if (attr.Name == "Customization" ||
                                attr.Name == "Version")
                            {
                                list.Add(attr);
                            }
                        }
                        foreach (XmlAttribute attr in list)
                            el2.RemoveAttributeNode(attr);


                        el_info = m_feature_manager.AddElement("Fields.xml", el2.OuterXml);

                        PropSheetField prop_sheet_field = new PropSheetField(this.DefaultResourceFile, m_feature_folder, el_info);
                        lstPageElements_ContainingElements.Items.Add(prop_sheet_field);
                    }
                }
            }

        }

        private void btnPageElements_ImportContentType_Click(object sender, EventArgs e)
        {
            try
            {
                PropSheetContentType prop_sheet = lstPageElements_ContainingElements.SelectedItem as PropSheetContentType;
                if (prop_sheet == null)
                    throw new Exception("The selected object is not a content type.");

                string msg = "All data entered for this content type will be overwritten. Do you want to continue?";
                if (MessageBox.Show(msg, "Prompt", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.OK)
                    return;

                ImportContentType(prop_sheet);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void SaveAllPendingResourceChanges()
        {
            foreach (IPropertySheet sheet in lstPageElements_ContainingElements.Items)
            {
                if (sheet.HasUnsavedResourceChanges)
                {
                    sheet.SaveChanges();
                }
            }

            if (m_main_info.HasUnsavedResourceChanges)
                m_main_info.SaveChanges();
        }

        private bool HasPendingResourceChanges()
        {
            bool ret = false;
            foreach (IPropertySheet sheet in lstPageElements_ContainingElements.Items)
            {
                if (sheet.HasUnsavedResourceChanges)
                {
                    ret = true;
                    break;
                }
            }

            if (m_main_info.HasUnsavedResourceChanges)
                ret = true;

            return ret;
        }

        private void btnPageElements_PickResource_Click(object sender, EventArgs e)
        {
            try
            {
                if (grdPageElements_Properties.SelectedObject == null)
                    return;

                if (grdPageElements_Properties.SelectedGridItem.PropertyDescriptor.IsReadOnly)
                    return;

                grdPageElements_Properties.Focus();

                GridItem item = grdPageElements_Properties.SelectedGridItem;
                object o = grdPageElements_Properties.SelectedObject;

                string name = o.ToString();
                /*
                if (o is PropSheetContentType)
                    name = (o as PropSheetContentType).Name.RawString;
                else if (o is PropSheetCustomAction)
                    name = (o as PropSheetCustomAction).Title.RawString;
                else if (o is PropSheetField)
                    name = (o as PropSheetField).Name;
                else if (o is PropSheetListInstance)
                    name = (o as PropSheetListInstance).Title.RawString;
                else if (o is PropSheetListTemplate)
                    name = (o as PropSheetListTemplate).Name;
                else if (o is PropSheetModule)
                    name = (o as PropSheetModule).Name;

                if (name == string.Empty)
                {
                    name = (o as IPropertySheet).ElementInfo.ElementName + (o as IPropertySheet).ElementInfo.ID.ToString();
                }
                */

                name = name.Replace(" ", "_").Replace("<","").Replace(">","");

                PickResource(grdPageElements_Properties, item, "Element_" + name);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageGeneral_PickResource_Click(object sender, EventArgs e)
        {
            try
            {
                if (grdPageGeneral_MainInfo.SelectedObject == null)
                    return;

                if (grdPageGeneral_MainInfo.SelectedGridItem.PropertyDescriptor.IsReadOnly)
                    return;

                grdPageGeneral_MainInfo.Focus();

                GridItem item = grdPageGeneral_MainInfo.SelectedGridItem;

                PickResource(grdPageGeneral_MainInfo, item, "Feature");

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private bool CheckForPendingResourceChanges()
        {

            if (HasPendingResourceChanges())
            {
                bool bSave = true;

                if (!Connect.S_Resources_Dont_Ask_before_save)
                {
                    using (DialogYesNoRepeatable dialog = new DialogYesNoRepeatable())
                    {
                        dialog.DialogMessage = "There are unsaved resource changes made which will be discarded if not saved before opening the editor. Do you want to save them before opening the editor?";
                        dialog.DefaultButtonSelect = true;
                        dialog.CheckBoxText = "If answering yes, resources will be saved as needed without asking in the future.";

                        DialogResult result = dialog.ShowDialog();
                        if (result == DialogResult.Cancel)
                            return false;

                        Connect.S_Resources_Dont_Ask_before_save = dialog.RepeatAction && (result == DialogResult.Yes);

                        bSave = (result != DialogResult.No);
                    }
                }

                try
                {
                    if (bSave)
                    {
                        SaveAllPendingResourceChanges();
                    }
                }
                catch
                {
                    Connect.S_Resources_Dont_Ask_before_save = false;
                    throw;
                }
            }

            return true;

        }

        private void PickResource(PropertyGrid Grid, GridItem Property, string SuggestedNamePrefix)
        {
            if (!CheckForPendingResourceChanges())
                return;


            if (SuggestedNamePrefix == null)
            {
                string default_res_file = string.IsNullOrEmpty(m_resource_editor_last_used_file) ? this.DefaultResourceFile : m_resource_editor_last_used_file;

                using (DialogResourceEditor dialog = new DialogResourceEditor(m_feature_folder, default_res_file, null))
                {
                    dialog.Text = "Resource editor";
                    DialogResult result = dialog.ShowDialog(this);

                    m_resource_editor_last_used_file = dialog.SelectedResourceFile;
                }

                InvalidateResourceCache();

                grdPageElements_Properties.Refresh();
                grdPageGeneral_MainInfo.Refresh();
            }
            else
            {
                string field = Property.PropertyDescriptor.Name;
                ResourceStringContainer res_container = Property.Value as ResourceStringContainer;

                string raw_string = res_container.RawString;
                string value = null;

                if (ResourceHelper.IsResourceString(raw_string))
                {
                    string msg = "Do you want to replace this fields resource bindings?";
                    if (MessageBox.Show(msg, "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) != DialogResult.Yes)
                        return;
                }

                try
                {
                    string s = "$Resources:" + SuggestedNamePrefix + "_" + field;

                    using (DialogResourceEditor dialog = new DialogResourceEditor(m_feature_folder, this.DefaultResourceFile, s))
                    {
                        dialog.Text = "Select a resource to bind to the property " + Property.PropertyDescriptor.Name;    
                        DialogResult result = dialog.ShowDialog(this);

                        m_resource_editor_last_used_file = dialog.SelectedResourceFile;

                        if (result == DialogResult.OK && !string.IsNullOrEmpty(dialog.ResourceString))
                        {
                            value = dialog.ResourceString;
                        }
                    }

                    if (value != null)
                    {
                        InvalidateResourceCache();

                        res_container = new ResourceStringContainer(value, this.DefaultResourceFile, m_feature_folder);
                        Property.PropertyDescriptor.SetValue(Grid.SelectedObject, res_container);

                        if (Grid.Name == "grdPageElements_Properties")
                        {
                            if (lstPageElements_ContainingElements.SelectedIndex != -1)
                                lstPageElements_ContainingElements.Items[lstPageElements_ContainingElements.SelectedIndex] = Grid.SelectedObject;

                            lstPageElements_ContainingElements.Refresh();
                        }
                    }

                }
                catch
                {
                    InvalidateResourceCache();
                    throw;

                }
                finally
                {
                    Grid.Refresh();
                    Property.Select();
                }



            }
        }

        private void btnResourceEditor_Click(object sender, EventArgs e)
        {
            try
            {
                PropertyGrid grid = null;
                if (tabControl.SelectedTab.Name == "tabPageGeneral")
                    grid = grdPageGeneral_MainInfo;
                else if (tabControl.SelectedTab.Name == "tabPageElements")
                    grid = grdPageElements_Properties;

                GridItem item = null;
                if (grid != null && grid.SelectedGridItem != null)
                {
                    if (grid.SelectedGridItem.Value is ResourceStringContainer)
                        item = grid.SelectedGridItem;
                }

                PickResource(grid, item, null);

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private struct ValidationMessageInfo
        {
            public string Message;
            public bool CanContinue;

            public ValidationMessageInfo(string Message, bool CanContinue)
            {
                this.Message = Message;
                this.CanContinue = CanContinue;
            }
        }

        private bool ValidateForm(bool noPrompt)
        {
            List<ValidationMessageInfo> msg_list = new List<ValidationMessageInfo>();

            try
            {
                Guid g = new Guid(FeatureID);
            }
            catch
            {
                msg_list.Add(new ValidationMessageInfo("Feature ID is invalid.", false));
            }

            if (m_main_info.Scope == FeatureScopeEnum.ScopeInvalid)
            {
                msg_list.Add(new ValidationMessageInfo("Feature scope is invalid.", false));
            }


            foreach (object prop_sheet in lstPageElements_ContainingElements.Items)
            {
                if (prop_sheet is PropSheetContentType)
                {
                    PropSheetContentType sheet = prop_sheet as PropSheetContentType;
                    if (string.IsNullOrEmpty(sheet.ID))
                    {
                        string s = sheet.Name.RawString;
                        if (string.IsNullOrEmpty(sheet.Name.RawString))
                            s = "(no name)";

                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Content type '{0}' has invalid ID.", s), false));
                    }

                    if (CountContentTypesWithID(sheet.ID) > 1)
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Content type '{0}' is already in use by another content type in this feature.", sheet.ID), false));
                    }

                    if (string.IsNullOrEmpty(sheet.Name.RawString))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Content type '{0}' is missing name. This content type may not install correctly.", sheet.ID), true));
                    }

                    if (string.IsNullOrEmpty(sheet.Group.RawString))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Content type '{0}' is missing group name. This content type may not install correctly.", sheet.ID), true));
                    }

                }

                else if (prop_sheet is PropSheetField)
                {
                    PropSheetField sheet = prop_sheet as PropSheetField;

                    try
                    {
                        Guid g = new Guid(sheet.ID);
                    }
                    catch
                    {
                        string s = sheet.Name;
                        if (string.IsNullOrEmpty(sheet.Name))
                            s = "(no name)";

                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Field '{0}' has invalid ID.", s), false));
                    }

                    if (string.IsNullOrEmpty(sheet.Name))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Field '{0}' has invalid name.", sheet.ID), true));
                    }

                    if (string.IsNullOrEmpty(sheet.Type))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"Field '{0}' has invalid field type.", sheet.ID), true));
                    }
                }

                else if (prop_sheet is PropSheetListInstance)
                {
                    PropSheetListInstance sheet = prop_sheet as PropSheetListInstance;
                    if (string.IsNullOrEmpty(sheet.Url.RawString))
                    {
                        string s = sheet.Title.RawString;
                        if (string.IsNullOrEmpty(sheet.Title.RawString))
                            s = "(no name)";

                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List instance '{0}' has invalid URL.", s), false));
                    }

                    if (string.IsNullOrEmpty(sheet.TemplateType))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List instance '{0}' has invalid template type.", sheet.Url.GetValue(null)), true));
                    }
                }

                else if (prop_sheet is PropSheetListTemplate)
                {
                    PropSheetListTemplate sheet = prop_sheet as PropSheetListTemplate;
                    if (string.IsNullOrEmpty(sheet.Name))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List template '{0}' has invalid name.", sheet.Type.ToString()), false));
                    }

                    if (string.IsNullOrEmpty(sheet.OriginalType.TemplateName) && sheet.ElementInfo.New)
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List template '{0}' has invalid built-in template type to copy from.", sheet.Name.ToString()), false));
                    }

                    if (sheet.Type < 1)
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"List template '{0}' has invalid template type.", sheet.Name.ToString()), false));
                    }
                    else
                    {
                        if (CountListTemplatesOfType(sheet.Type) > 1)
                        {
                            msg_list.Add(new ValidationMessageInfo(string.Format(@"List template {0} has type {1} that is already in use by another list template in this feature.", sheet.Name, sheet.Type.ToString()), false));
                        }
                    }
                }

                else if (prop_sheet is PropSheetModule)
                {
                    PropSheetModule sheet = prop_sheet as PropSheetModule;
                    if (string.IsNullOrEmpty(sheet.Name))
                    {
                        msg_list.Add(new ValidationMessageInfo(string.Format(@"One module element has invalid name."), false));
                    }
                }
            }


            if (msg_list.Count > 0)
            {
                foreach (ValidationMessageInfo info in msg_list)
                {
                    if (noPrompt)
                    {
                        if (!info.CanContinue)
                            return false;
                    }
                    else
                    {
                        if (info.CanContinue)
                        {
                            DialogResult result = MessageBox.Show(info.Message + " Do you want to continue?", "Validation error.", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
                            if (result == DialogResult.Cancel)
                                return false;
                        }
                        else
                        {
                            MessageBox.Show(info.Message, "Validation error.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return false;
                        }
                    }
                }
            }

            return true;
        }

        private void btnPageActivationDep_add_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrEmpty(cboPageActivationDep_FeatureToAdd.Text))
                    return;

                string feature_id_str;
                string name;
                string[] arr = cboPageActivationDep_FeatureToAdd.Text.Trim().Split(':');

                if (arr.Length > 1)
                {
                    name = arr[0].Trim();
                    feature_id_str = arr[1].Trim().ToUpper();
                }
                else
                {
                    name = "(feature not in project)";
                    feature_id_str = arr[0].Trim().ToUpper();
                }

                Guid feature_id;
                try
                {
                    feature_id = new Guid(feature_id_str);
                }
                catch
                {
                    string msg = "The id is not in GUID format.";
                    MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (m_features_in_project.ContainsKey(feature_id))
                    name = m_features_in_project[feature_id];

                foreach (string s in lstPageActivationDep_List.Items)
                {
                    string[] arr2 = s.Split(':');
                    if (new Guid(arr2[1].Trim().ToUpper()) == feature_id)
                    {
                        string msg = "The id is already in the list.";
                        MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }

                lstPageActivationDep_List.Items.Add(name + ":" + feature_id_str);
                m_feature_manager.ActivationDependencies.Add(feature_id);

                cboPageActivationDep_FeatureToAdd.Text = string.Empty;

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnPageActivationDep_delete_Click(object sender, EventArgs e)
        {
            try
            {
                string s = lstPageActivationDep_List.SelectedItem as string;

                if (s != null)
                {

                    string msg = "Do you want to remove the feature '" + s + "' from the activation dependencies list?";
                    DialogResult result = MessageBox.Show(msg, "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);

                    if (result == DialogResult.Yes)
                    {
                        string[] arr = s.Split(':');

                        lstPageActivationDep_List.Items.RemoveAt(lstPageActivationDep_List.SelectedIndex);
                        m_feature_manager.ActivationDependencies.Remove(new Guid(arr[1].Trim().ToUpper()));
                    }
                }

            }
            catch (Exception ex)
            {
                DialogError.ShowError(ex, false);
            }
        }

        private void btnDefaultCodeFolder_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Do you want to restore the default code folder?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
            {
                this.txtDefaultCodeFolder.Text = "<Feature folder>\\CodeFiles";
            }
        }

        private void btnPickDefaultCodeFolder_Click(object sender, EventArgs e)
        {
            using (DialogCodeFileSelector dialog = new DialogCodeFileSelector(m_special_project.Project, string.Empty))
            {
                dialog.FolderView = true;
                dialog.rdoProjectFiles.Checked = true;
                dialog.rdoClasses.Enabled = false;

                string path = this.txtDefaultCodeFolder.Text;
                if (path.StartsWith("<Feature folder>\\", StringComparison.OrdinalIgnoreCase))
                {
                    path = path.Replace("<Feature folder>", Common.GetProjectItemPath(m_feature_folder, true));
                }
                else if (path.StartsWith("<Project root>\\", StringComparison.OrdinalIgnoreCase))
                {
                    path = path.Replace("<Project root>\\", "");
                }

                dialog.StartupFolder = path;

                DialogResult result = dialog.ShowDialog(this);
                if (result != DialogResult.OK)
                    return;

                ProjectItem folder = dialog.SelectedItem;
                if (folder == null)
                {
                    this.txtDefaultCodeFolder.Text = "<Project root>\\";
                }
                else
                {
                    this.txtDefaultCodeFolder.Text = "<Project root>\\" + Common.GetProjectItemPath(folder, true);
                }
            }
        }

    }
}
